include(CheckCXXSourceCompiles)

if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_SIMULATE_ID MATCHES "MSVC" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "MSVC")
    set(CMAKE_REQUIRED_FLAGS "/arch:SSE")
elseif(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
    set(CMAKE_REQUIRED_FLAGS "-msse")
endif()
check_cxx_source_compiles("#include <xmmintrin.h>\nint main() { __m128 u, v; u = _mm_set1_ps(0.0f); v = _mm_shuffle_ps(u, u, _MM_SHUFFLE(3, 3, 1, 1)); return 0; }" AC_COMPILER_SUPPORT_SSE)

if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_SIMULATE_ID MATCHES "MSVC" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "MSVC")
    set(CMAKE_REQUIRED_FLAGS "/arch:SSE2")
elseif(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
    set(CMAKE_REQUIRED_FLAGS "-msse2")
endif()
check_cxx_source_compiles("#include <emmintrin.h>\nint main() { __m128i a = _mm_set1_epi32(1); return 0; }" AC_COMPILER_SUPPORT_SSE2)

if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_SIMULATE_ID MATCHES "MSVC" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "MSVC")
    set(CMAKE_REQUIRED_FLAGS "/arch:AVX")
elseif(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
    set(CMAKE_REQUIRED_FLAGS "-mavx")
endif()
check_cxx_source_compiles("#include <immintrin.h>\nint main() { __m256 a = _mm256_set1_ps(0.0f); return 0; }" AC_COMPILER_SUPPORT_AVX)

if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_SIMULATE_ID MATCHES "MSVC" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "MSVC")
    set(CMAKE_REQUIRED_FLAGS "/arch:AVX2")
elseif(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
    set(CMAKE_REQUIRED_FLAGS "-mavx2")
endif()
check_cxx_source_compiles("#include <immintrin.h>\nint main() { __m256i a = _mm256_set1_epi32(0); return 0; }" AC_COMPILER_SUPPORT_AVX2)

if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_SIMULATE_ID MATCHES "MSVC" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "MSVC")
    set(CMAKE_REQUIRED_FLAGS "/arch:AVX2")
elseif(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
    set(CMAKE_REQUIRED_FLAGS "-mfma")
endif()
check_cxx_source_compiles("#include <immintrin.h>\nint main() { __m256 s0, s1, s2; s0 = _mm256_fmadd_ps(s1, s2, s0); return 0; }" AC_COMPILER_SUPPORT_FMA)

if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_SIMULATE_ID MATCHES "MSVC" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "MSVC")
    set(CMAKE_REQUIRED_FLAGS "/arch:armv8.0")
elseif(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
    if(BUILD_ARCH_32BIT)
        set(CMAKE_REQUIRED_FLAGS "-mfpu=neon")
    else()
        set(CMAKE_REQUIRED_FLAGS "-march=armv8-a")
    endif()
endif()
check_cxx_source_compiles("#include <arm_neon.h>\nint main() { float32x4_t a = vdupq_n_f32(0.0f); return 0; }" AC_COMPILER_SUPPORT_NEON)

if(NOT (CMAKE_CXX_COMPILER_ID MATCHES "MSVC" OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_SIMULATE_ID MATCHES "MSVC" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "MSVC")))
    set(CMAKE_REQUIRED_FLAGS "-msimd128")
endif()
check_cxx_source_compiles("#include <wasm_simd128.h>\nint main() { v128_t a = wasm_f32x4_make(1.2f, 3.4f, 5.6f, 7.8f); return 0; }" AC_COMPILER_SUPPORT_WASM_SIMD128)

if ((CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_SIMULATE_ID MATCHES "MSVC" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES "MSVC") OR (NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC"))
    unset(CMAKE_REQUIRED_FLAGS)
endif()
